package com.iol.stpso.util;

//import java.io.ByteArrayOutputStream;

public class Base64
{
	public final static String BASE64CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	
	//编码
	public static String encode(byte[] byts)
	{
		StringBuffer buf = new StringBuffer();//编码后的内容
		char[] asc = new char[4];//4个ASCII
		int n = 1;//编码次数；
		int j = 0;//处理后的每个字节
		int k = 0;
		
		for (int i = 0; i < byts.length; i++)
			{
			//每个字节
			int i1 = byts[i] < 0 ? (byts[i] & 0x7F) + 128 : byts[i];
			switch (n)
			{
			case 1:
				asc[0] = BASE64CHARS.charAt(i1 >>> 2);
				j = i1 & 0x3;
				break;
			case 2:
				asc[1] = BASE64CHARS.charAt(j << 4 | i1 >>> 4);
				j = i1 & 0xF;
				break;
			case 3:
				asc[2] = BASE64CHARS.charAt(j << 2 | i1 >>> 6);
		        asc[3] = BASE64CHARS.charAt(i1 & 0x3F);
		        buf.append(asc);
		        k++; 
		        if (k % 19 != 0) break;
		        buf.append("\r\n"); break;
		      }
			//最大3次
			n = n >= 3 ? 1 : n + 1;
			}
		
		switch (n)
		    {
		    case 2:
		      asc[1] = BASE64CHARS.charAt(j << 4);
		      asc[2] = 61;
		      asc[3] = 61;
		      buf.append(asc);
		      break;
		    case 3:
		      asc[2] = BASE64CHARS.charAt(j << 2);
		      asc[3] = '=';
		      buf.append(asc);
		    }
		
		return buf.toString();
	}
	
	//解码
	public static String decode( String ascStr ) {
		
		int ascStrL = ascStr.length();
		int n = ascStrL/4;
		int ascStrEnd = ascStr.endsWith("==")?2:(ascStr.endsWith("=")?1:0);
		byte[] byts = new byte[3*n];
		byte[] ascByte = new byte[4];
	//	ByteArrayOutputStream out = new ByteArrayOutputStream(strl);
		
		if (ascStrL%4 != 0)
			throw new RuntimeException( "valid Base64 codes have a multiple of 4 characters" );
		
		for (int g = 0; g < n; g++) {
			for (int i = 0; i < ascByte.length; i++) {
				ascByte[i] = (byte) Math.max( 0, BASE64CHARS.indexOf( ascStr.charAt( 4*g+i ) ) );
				}
			convert4To3( ascByte, byts, g*3 );
//          out.write(byts, 0, byts.length - ascStrEnd);
			}		
//      return out.toByteArray();
		return new String(byts, 0, byts.length - ascStrEnd);
		
	}
	
	private static void convert4To3( byte[] ascByte, byte[] byts, int bytsIndex ) {
		byts[ bytsIndex  ]  = (byte) (( ascByte[0] << 2) | (ascByte[1] >>> 4));
		byts[ bytsIndex+1 ] = (byte) (((ascByte[1] & 0x0f) << 4) | (ascByte[2] >>> 2));
		byts[ bytsIndex+2 ] = (byte) (((ascByte[2] & 0x03) << 6) | (ascByte[3]));
		}
}